// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//                            avtPVLDFileFormat.h                           //
// ************************************************************************* //

#ifndef AVT_PVLD_FILE_FORMAT_H
#define AVT_PVLD_FILE_FORMAT_H

#include <avtSTMDFileFormat.h>

#include <pvldReader.h>
#include <pvldPartReader.h>

class vtkFloatArray;
class vtkPoints;
class vtkUnstructuredGrid;

// ****************************************************************************
//  Class: avtPVLDFileFormat
//
//  Purpose:
//      Reads in PVLD files as a plugin to VisIt.
//
//  Programmer: hpan -- generated by xml2avt
//  Creation:   Tue Sep 25 14:55:38 PST 2012
//
//  Modifications:
//    Brad Whitlock, Fri Jun 20 13:05:07 PDT 2014
//    Add time-varying metadata.
//
// ****************************************************************************

class avtPVLDFileFormat : public avtSTMDFileFormat
{
public:
    avtPVLDFileFormat(const char *);
    virtual           ~avtPVLDFileFormat();

    //
    // This is used to return unconvention data -- ranging from material
    // information to information about block connectivity.
    //
    virtual void      *GetAuxiliaryData(const char *var, int domain,
                                        const char *type, void *args,
                                        DestructorFunction &);


    virtual int       GetCycle(void)
    {
        return preader_->GetCycle();
    }
    virtual double    GetTime(void)
    {
        return preader_->GetTime();
    }

    // Tell VisIt that the Metadata and SIL change over time.
    bool                   HasInvariantMetaData(void) const
    {
        return false;
    }

    bool                   HasInvariantSIL(void) const
    {
        return false;
    }

    void                   ActivateTimestep(void);
    virtual const char    *GetType(void)
    {
        return "PVLD";
    };
    virtual void           FreeUpResources(void);

    virtual vtkDataSet    *GetMesh(int, const char *);
    virtual vtkDataArray  *GetVar(int, const char *);
    virtual vtkDataArray  *GetVectorVar(int, const char *);

protected:
    // DATA MEMBERS
    bool  hasTOCread_;
    bool  add_missing_parts_;
    bool  enablePVLD;
    PVLD_Reader  *preader_;

    virtual void           PopulateDatabaseMetaData(avtDatabaseMetaData *);

protected:
    void ReadTOC();

    void AddSolidMesh( avtDatabaseMetaData *md );
    void AddShellMesh( avtDatabaseMetaData *md );
    void AddBeamMesh(  avtDatabaseMetaData *md );
    void AddSurfaceMesh( avtDatabaseMetaData *md );
    void AddSphMesh( avtDatabaseMetaData *md );
    void AddTiedSetMesh( avtDatabaseMetaData *md );
    void AddContactMesh( avtDatabaseMetaData *md );

    void AddSolidVariables( avtDatabaseMetaData *md );
    void AddShellVariables( avtDatabaseMetaData *md );
    void AddBeamVariables(  avtDatabaseMetaData *md );
    void AddSurfaceVariables( avtDatabaseMetaData *md );
    void AddNodeVariables( const std::string& meshname, avtDatabaseMetaData *md );
    void AddSphVariables( avtDatabaseMetaData *md );
    void AddTiedSetVariables( avtDatabaseMetaData *md );
    void AddContactVariables( avtDatabaseMetaData *md );

    void AddSolidMaterial( avtDatabaseMetaData *md );
    void AddShellMaterial( avtDatabaseMetaData *md );
    void AddBeamMaterial(  avtDatabaseMetaData *md );
    void AddSurfaceMaterial( avtDatabaseMetaData *md );
    void AddSphMaterial( avtDatabaseMetaData *md );

    vtkPoints *MakePoints(std::vector<float> &crd);

    vtkUnstructuredGrid* GenerateSolidMesh( std::vector<float>& crd, const std::vector<int>& elm );
    vtkUnstructuredGrid* GenerateShellMesh( std::vector<float>& crd, const std::vector<int>& elm );
    vtkUnstructuredGrid* GenerateBeamMesh(  std::vector<float>& crd, const std::vector<int>& elm );
    vtkUnstructuredGrid* GenerateSphMesh( std::vector<float>& crd, const std::vector<int>& elm );
    vtkUnstructuredGrid* GeneratePointMesh( std::vector<float>& crd );
    vtkUnstructuredGrid* GenerateBondMesh( const std::vector<float>& crd1, const std::vector<float>& crd2 );

    void CreateGlobalNodeIds(int domain, const char *meshname, const std::vector<int> &vmap);

    vtkFloatArray* GenerateVariable( const std::vector<int>& dim, std::vector<float>& dat );
    vtkFloatArray* GenerateDyna3dStressTensor( const std::vector<int>& dims, const std::vector<float>& dat );
    vtkFloatArray* GenerateSphStressTensor( const std::vector<int>& dims, const std::vector<float>& dat );


    void AddSolidIndexVariables( avtDatabaseMetaData *md );
    void AddShellIndexVariables( avtDatabaseMetaData *md );
    void AddIndexVariables( const std::string& meshname,
                            const std::string& idxname,
                            const std::vector<std::string>& dsname,
                            const std::vector<std::vector<int> >& dsdims,
                            avtDatabaseMetaData *md );

};


#endif
